package com.tollge.snowflake_registry;

import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Promise;
import io.vertx.core.eventbus.Message;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.JsonObject;
import io.vertx.core.json.jackson.DatabindCodec;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.BodyHandler;
import lombok.extern.log4j.Log4j2;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Log4j2
public class MainVerticle extends AbstractVerticle {

  @Override
  public void start(Promise<Void> startPromise) throws Exception {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    LocalDateTimeSerializer localDateTimeSerializer = new LocalDateTimeSerializer(formatter);
    LocalDateTimeDeserializer localDateTimeDeserializer = new LocalDateTimeDeserializer(formatter);
    JavaTimeModule javaTimeModule = new JavaTimeModule();
    javaTimeModule.addSerializer(LocalDateTime.class, localDateTimeSerializer);
    javaTimeModule.addDeserializer(LocalDateTime.class, localDateTimeDeserializer);

    DatabindCodec.mapper().registerModule(javaTimeModule);
    DatabindCodec.mapper().findAndRegisterModules();

    // 构建verticle
    DeploymentOptions options = new DeploymentOptions().setWorkerPoolName("snowflake").setWorker(true).setWorkerPoolSize(1).setInstances(1);
    FetchSnowflakeVerticle fetchSnowflakeVerticle = new FetchSnowflakeVerticle();
    vertx.deployVerticle(fetchSnowflakeVerticle, options);

    // 启动web服务
    HttpServer server = vertx.createHttpServer();

    Router router = Router.router(vertx);

    router.route("/health").handler(ctx -> {

      // This handler will be called for every request
      HttpServerResponse response = ctx.response();
      response.putHeader("content-type", "text/plain");

      // Write to the response and end it
      response.end("success");
    });

    router.post("/inner/fetchMachineCode").handler(BodyHandler.create()).handler(ctx -> {
      JsonObject json = ctx.getBody() == null || ctx.getBody().length() == 0 ? new JsonObject() : ctx.getBodyAsJson();

      // This handler will be called for every request
      HttpServerResponse response = ctx.response();
      response.putHeader("content-type", "application/json");

      vertx.eventBus().<JsonObject>request("fetchMachineCode", json, res -> {
        if (res.succeeded()) {
          Message<JsonObject> result = res.result();
          // Write to the response and end it
          response.end(result.body().toString());
        } else {
          log.error("fetchMachineCode failed", res.cause());
        }
      });
    });

    server.requestHandler(router).listen(8080, http -> {
      if (http.succeeded()) {
        startPromise.complete();
        log.info("HTTP server started on port 8080");
      } else {
        log.error("HTTP server started failed", http.cause());
        startPromise.fail(http.cause());
      }
    });

  }
}
